#include "globals.h"
#include "symtab.h"
#include "analyze.h"

static int location =0;

static void nullproc(TreeNode *t){
  if(t==NULL)
    return;
  else return;
}
static void traverse(TreeNode *t,
                     void(*preProc) (TreeNode *),
                     void(*postProc) (TreeNode *)){
  if(t!=NULL){
    preProc(t);
    {
      int i;
      for(i=0;i<MAXCHILDREN;i++){
        traverse(t->child[i],preProc,postProc);
    }
    }
    postProc(t);
    traverse(t->sibling,preProc,postProc);
  }
}

static void insertNode(TreeNode *t){
  switch(t->nodekind){
  case StmtK:
    switch(t->kind.stmt){
    case AssignK:
    case ReadK:
      if(st_lookup(t->attr.name)==-1)
        st_insert(t->attr.name,t->lineno,location++);
      else
        st_insert(t->attr.name,t->lineno,0);
      break;
    default:
      break;
  }
    break;
  case ExpK:
    switch(t->kind.exp){
    case IdK:
      if(st_lookup(t->attr.name)==-1)
        st_insert(t->attr.name,t->lineno,location++);
      else
        st_insert(t->attr.name,t->lineno,0);
      break;
    default:
      break;
    }
    break;
  default:
   break;
  }
}
void buildSymtab(TreeNode * syntaxTree){
  if(syntaxTree!=NULL){
  traverse(syntaxTree, insertNode,nullproc);
  printSymTab(listing);
  }
}


static void checkNode(TreeNode *t){
  switch(t->nodekind){
  case ExpK:
    switch(t->kind.exp){
    case OpK:
      if((t->child[0]->type!=Integer)||(t->child[1]->type!=Integer))
        fprintf(listing,"op applied to non-integer\n");
      if((t->attr.op==EQUAL)||(t->attr.op==LESS))
        t->type=Boolean;
      else
        t->type=Integer;
      break;
    case ConstK:
    case IdK:
      t->type=Integer;
      break;
    default:
      break;
    }
    break;
  case StmtK:
    switch(t->kind.stmt){
    case IfK:
      if(t->child[0]->type==Integer)
        fprintf(listing,"if test is not Boolean");
      break;
    case AssignK:
      if(t->child[0]->type!=Integer)
        fprintf(listing,"assignment of non-integer value");
      break;
    case WriteK:
      if(t->child[0]->type!=Integer)
        fprintf(listing,"assignment of non-integer value");
      break;
    case RepeatK:
      if(t->child[1]->type==Integer)
        fprintf(listing,"repeat test is not Boolean");
      break;
    default:
      break;
    }
    break;
  default:
    break;
  }
}
void typeCheck(TreeNode * syntaxTree){
  if(syntaxTree!=NULL){
    traverse(syntaxTree, nullproc, checkNode);
    //Post traverse
  }
}
